package dev.tools.design.patterns.command;

import dev.tools.design.patterns.command.states.Aborted;
import dev.tools.design.patterns.command.states.Created;
import dev.tools.design.patterns.command.states.Finished;
import dev.tools.design.patterns.command.states.Started;
import dev.tools.design.patterns.state.Context;

/**
 * Created with IntelliJ IDEA.
 * User: Nuno
 * Date: 02-10-2013
 * Time: 18:16
 */
public abstract class Command extends Context<Command, Command.State> implements ICommand{
    public static final Created CREATED = new Created();
    public static final Started STARTED = new Started();
    public static final Finished FINISHED = new Finished();
    public static final Aborted ABORTED = new Aborted();

    private Object result;
    private Throwable cause;

    protected Command(){
        super(CREATED);
    }

    public final void execute(){
        setState(STARTED);
        try{
            protectedExecute();
            setState(FINISHED);
        }catch (CommandException e){
            setState(ABORTED);
            this.cause = e.getCause();
        }
    }

    protected abstract void protectedExecute() throws CommandException;

    public Throwable getCause() {
        return cause;
    }

    public Object getResult() {
        return result;
    }

    protected void setResult(Object result) {
        this.result = result;
    }

    public Command addFinishHandler(IStateHandler handler){
        return addHandler(handler, FINISHED);
    }

    public Command addAbortHandler(IStateHandler handler){
        return addHandler(handler, ABORTED);
    }

    public static class State extends dev.tools.design.patterns.state.State<Command, State>{
    }

    public static interface IStateHandler extends dev.tools.design.patterns.state.IStateHandler<Command, State>{
    }
}
